home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / CALib & You… / Source / CASample / CAS_StringTools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-07  |  16.7 KB  |  740 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CAS_StringTools.c
  3.  
  4.     Contains:    Utility routines for strings.
  5.  
  6.     Written by:    David H Nelson
  7.  
  8.     Copyright © 1988-1995 ComponentWorks, All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <1>     1988    DHN        Created.
  13.  
  14. */
  15.  
  16. #include "CAS_CTools.h"
  17. #include "CAS_StringTools.h"
  18.  
  19. static Str63    pluralStr, singularStr;
  20.  
  21.  
  22. //----------------------------------------------------------------------
  23. // Convert a C string to a Pascal string
  24. // Be careful, a routine with the same name exists in LSC 4.0 "CtoPStr:
  25. StringPtr ctopstr(char *s)
  26. {
  27.     return((StringPtr) CtoPstr(s));
  28. }
  29.  
  30. //----------------------------------------------------------------------
  31. // Convert a Pascal string to a C string
  32. // Be careful, a routine with the same name exists in LSC 4.0 "PtoCStr:
  33. char *ptocstr(Str255 s)
  34. {
  35.     return(PtoCstr(s));
  36. }
  37.  
  38. //----------------------------------------------------------------------
  39. // Get the individual string from 'STR#' iRedID and item iStringID into the
  40. // global resStr.
  41. StringPtr sGetResString(short iResID, short iStringID)
  42. {
  43.     resStr[0] = 0;
  44.     GetIndString(resStr,iResID,iStringID);
  45.     return(resStr);
  46. }
  47.  
  48. //----------------------------------------------------------------------
  49.  
  50. short iStrPos(register Str255 s, register char c)
  51. {
  52.     StringPtr            s0 = s;
  53.     register StringPtr    e;
  54.  
  55.     e = s + (long) *s + 1; // 1 past end of string
  56.     s++;
  57.  
  58.     while ((s < e) && (*s != c)) s++;
  59.  
  60.     return ( (s < e && *s == c) ? s-s0 : -1 );
  61. }
  62.  
  63. //----------------------------------------------------------------------
  64. // convert the character into uppercase if it's an English letter.
  65. char cUpperCase(register char c)
  66. {
  67.     return((c > 0x60 && c < 0x7B) ? c-0x20 : c);
  68. }
  69.  
  70. //----------------------------------------------------------------------
  71. // Substitute up to 10 strings into the given string at the ^0 through ^9 positions
  72. // in the string. All ^X are removed from the string. Nil may be passed for any 
  73. // of the substitution strings.
  74. StringPtr sParamStr(
  75.     Str255    theStr,
  76.     Str255    s0,
  77.     Str255    s1,
  78.     Str255    s2,
  79.     Str255    s3,
  80.     Str255    s4,
  81.     Str255    s5,
  82.     Str255    s6,
  83.     Str255    s7,
  84.     Str255    s8,
  85.     Str255    s9 )
  86. {
  87. Handle    hStr;
  88. Str31    sSearch;
  89.  
  90.     hStr = NewHandle( theStr[0] );
  91.     if (hStr == nil)
  92.         theStr[0] = '\0';
  93.     else
  94.     {
  95.         BlockMoveData( &theStr[1], *hStr, (long)(theStr[0]) );
  96.  
  97.         if (s0 != nil)
  98.         {
  99.             sCopyStr( (StringPtr)"\p^0", sSearch );
  100.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s0[1], s0[0] );
  101.         }
  102.  
  103.         if (s1 != nil)
  104.         {
  105.             sCopyStr( (StringPtr)"\p^1", sSearch );
  106.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s1[1], s1[0] );
  107.         }
  108.  
  109.         if (s2 != nil)
  110.         {
  111.             sCopyStr( (StringPtr)"\p^2",sSearch);
  112.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s2[1], s2[0] );
  113.         }
  114.  
  115.         if (s3 != nil)
  116.         {
  117.             sCopyStr( (StringPtr)"\p^3",sSearch);
  118.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s3[1],s3[0] );
  119.         }
  120.  
  121.         if (s4 != nil)
  122.         {
  123.             sCopyStr( (StringPtr)"\p^4", sSearch );
  124.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s4[1],s4[0] );
  125.         }
  126.  
  127.         if (s5 != nil)
  128.         {
  129.             sCopyStr( (StringPtr)"\p^5", sSearch );
  130.             Munger( hStr, 0L, &sSearch[1], sSearch[0] ,&s5[1], s5[0] );
  131.         }
  132.  
  133.         if (s6 != nil)
  134.         {
  135.             sCopyStr( (StringPtr)"\p^6", sSearch );
  136.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s6[1], s6[0] );
  137.         }
  138.  
  139.         if (s7 != nil)
  140.         {
  141.             sCopyStr( (StringPtr)"\p^7", sSearch );
  142.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s7[1], s7[0] );
  143.         }
  144.  
  145.         if (s8 != nil)
  146.         {
  147.             sCopyStr( (StringPtr)"\p^8", sSearch );
  148.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s8[1], s8[0] );
  149.         }
  150.  
  151.         if (s9 != nil)
  152.         {
  153.             sCopyStr( (StringPtr)"\p^9", sSearch );
  154.             Munger( hStr, 0L, &sSearch[1], sSearch[0], &s9[1], s9[0] );
  155.         }
  156.  
  157.         theStr[0] = min( 255, GetHandleSize( hStr ) );
  158.         BlockMoveData( *hStr, &theStr[1], (long)(theStr[0]) );
  159.  
  160.         DisposeHandle( hStr );
  161.     }
  162.  
  163.     return theStr;
  164. }
  165.  
  166. //----------------------------------------------------------------------
  167. // convert the number (in seconds) to a string of the form 'about X minutes', or…
  168. // 'about a minute' or 'less than a minute'
  169. void NumToEstimatedTimeString(long TimeLeft,Str63 sTimeLeft)
  170. {
  171.     Str63    sMinutes;
  172.  
  173.     if (TimeLeft < 45)
  174.     {
  175.         GetIndString(sTimeLeft,CStringsID,38);    // less than a minute
  176.         return;
  177.     }
  178.  
  179.     if (TimeLeft < 90)
  180.     {
  181.         GetIndString( sTimeLeft, CStringsID, 39 );    // about a minute
  182.         return;
  183.     }
  184.  
  185.     NumToThousandString( (TimeLeft+30) / 60,sMinutes );
  186.  
  187.     GetIndString( sTimeLeft, CStringsID, 40 );        // about ^0 minutes
  188.     sParamStr( sTimeLeft, sMinutes, nil, nil, nil, nil, nil, nil, nil, nil, nil);
  189. }
  190.  
  191. //----------------------------------------------------------------------
  192. // convert the number (in seconds) to a string of the form 'HH:MM:SS'
  193. void NumToTimeLeftString(
  194.     long    TimeLeft,
  195.     Str63    sTimeLeft )
  196. {
  197. Str63    sMinutes, sSeconds;
  198. short    Hours, Minutes, Seconds;
  199.  
  200.     Hours   = TimeLeft / (60*60);
  201.     Minutes = (TimeLeft / 60) % 60;
  202.     Seconds = TimeLeft % 60;
  203.  
  204.     NumToString( (long)Hours, sTimeLeft );
  205.     NumToString( (long)Minutes, sMinutes );
  206.     NumToString( (long)Seconds, sSeconds );
  207.  
  208.     if (sMinutes[0] < 2)
  209.     {    // only 1 digit?
  210.         sMinutes[2] = sMinutes[1];
  211.         sMinutes[1] = '0';    // put in leading zero on minutes
  212.         sMinutes[0] = 2;
  213.     }
  214.  
  215.     while (sSeconds[0] < 2)
  216.     {    // only 1 digit?
  217.         sSeconds[2] = sSeconds[1];
  218.         sSeconds[1] = '0';    // put in leading zero on seconds
  219.         sSeconds[0] = 2;
  220.     }
  221.  
  222.     sTimeLeft[++sTimeLeft[0]] = ':';
  223.     sTimeLeft[++sTimeLeft[0]] = sMinutes[1];
  224.     sTimeLeft[++sTimeLeft[0]] = sMinutes[2];
  225.     sTimeLeft[++sTimeLeft[0]] = ':';
  226.     sTimeLeft[++sTimeLeft[0]] = sSeconds[1];
  227.     sTimeLeft[++sTimeLeft[0]] = sSeconds[2];
  228.  
  229. }
  230.  
  231. //----------------------------------------------------------------------
  232. // convert the number into a string (0-9) with the current int'l seperator at each
  233. // third digit.
  234. void NumToThousandString(long theLong,Str63 sThousandString)
  235. {
  236. char        theSep;
  237. Intl0Hndl    theIntl0Hndl;
  238. short        i, j;
  239.  
  240.     NumToString(theLong,sThousandString);
  241.  
  242.     theIntl0Hndl = (Intl0Hndl)IUGetIntl(0);
  243.     theSep = (**(Intl0Hndl)(IUGetIntl(0))).thousSep;
  244.  
  245.     i = sThousandString[0];
  246.     while (i>3)
  247.     {
  248.         i -= 2;
  249.         for (j = sThousandString[0]++; j >= i ; j--)
  250.             sThousandString[j+1] = sThousandString[j];
  251.  
  252.         sThousandString[i--] = theSep;
  253.     }
  254. }
  255.  
  256. //----------------------------------------------------------------------
  257. // convert the string of numbers (0-9 with embedded commas) into a number
  258. void ThousandStringToNum(Str63 sThousandString, long *theLong)
  259. {
  260.     char        theChar;
  261.     short        i,j;
  262.     Str63        s0;
  263.  
  264.     sCopyStr(sThousandString, s0);
  265.  
  266.     i = s0[0];
  267.     while (i>0)
  268.     {
  269.         theChar = s0[i];
  270.         if (theChar < '0' || theChar > '9')
  271.         {
  272.             j = i;
  273.             while (j<s0[0])
  274.             {
  275.                 s0[j] = s0[j+1];
  276.                 j++;
  277.             }
  278.             s0[0]--;
  279.         }
  280.         i--;
  281.     }
  282.     StringToNum(s0, theLong);
  283. }
  284.  
  285. //----------------------------------------------------------------------
  286. // convert theLong into a string of numbers rounded to the nearest 1K with the current
  287. // int'l seperator at each third digit.
  288. void NumToKString(long theLong, Str63 sKString)
  289. {
  290. //    char        theSep;
  291.  
  292.     theLong += 1023;    // round up
  293.  
  294.     theLong >>= 10;
  295.  
  296.     NumToThousandString(theLong, sKString);
  297. #if 0
  298.     theIntl0Hndl = (Intl0Hndl)IUGetIntl(0);
  299.     theSep = (**theIntl0Hndl).thousSep;
  300.  
  301.     i = sKString[0];
  302.     while (i>3)
  303.     {
  304.         i -= 2;
  305.         for (j = sKString[0]++; j >= i ; j--)
  306.         {
  307.             sKString[j+1] = sKString[j];
  308.         }
  309.         sKString[i--] = theSep;
  310.     }
  311. #endif
  312. }
  313.  
  314. #if false
  315. //----------------------------------------------------------------------
  316. // convert theLong into a string rounded to the nearest .5K
  317. void NumToKString(long theLong,Str63 sThousandString)
  318. {
  319.     Intl0Hndl    theIntl0Hndl;
  320.     short        i,j;
  321.     long        saveLong;
  322.  
  323.     theLong += 511;    // round up
  324.  
  325.     saveLong = theLong>>9;
  326.  
  327.     theLong >>= 10;
  328.  
  329.     NumToString(theLong,sThousandString);
  330.  
  331.     theIntl0Hndl = (Intl0Hndl)IUGetIntl(0);
  332.     theSep = (**theIntl0Hndl).thousSep;
  333.  
  334.     i = sThousandString[0];
  335.     while (i > 3)
  336.     {
  337.         i -= 2;
  338.         for (j = sThousandString[0]++; j >= i ; j--)
  339.         {
  340.             sThousandString[j+1] = sThousandString[j];
  341.         }
  342.         sThousandString[i--] = theSep;
  343.     }
  344.     // if it's zero, leave it.
  345.     // if it's between one and 511 make append '.5'
  346.     // otherwise round it to the nearest .5K
  347.     if (saveLong && (max(1,saveLong) & 0x1))
  348.     {
  349.         sThousandString[++sThousandString[0]] = (**theIntl0Hndl).decimalPt;
  350.         sThousandString[++sThousandString[0]] = '5';
  351.     }
  352. }
  353. #endif
  354.  
  355. //----------------------------------------------------------------------
  356. // convert theLong into a string (0-9) rounded to the nearest byte, KB, or MB
  357. // with the current int'l seperator at each third digit.
  358. void NumToSizeString(long theLong, Str63 sSizeString)
  359. {
  360. Str63    s0;
  361.  
  362.     if (theLong < 1024L)
  363.     {
  364.         GetIndString(sSizeString, sizeStrings, inByteSize);
  365.     }
  366.     else if (theLong < 1048576L)    // convert to nearest KB
  367.     {
  368.         theLong += 1023;            // round up to nearest KB
  369.         theLong >>= 10;
  370.  
  371.         GetIndString(sSizeString, sizeStrings, inKBSize);
  372.     }
  373.     else                            // convert to nearest MB
  374.     {
  375.         theLong += 1048576;            // round up to next MB
  376.         theLong >>= 20;
  377.  
  378.         GetIndString(sSizeString, sizeStrings, inMBSize);
  379.     }
  380.  
  381.     NumToThousandString( theLong, s0 );
  382.     sParamStr( sSizeString, s0, nil, nil, nil, nil, nil, nil, nil, nil, nil );
  383. }
  384.  
  385. //----------------------------------------------------------------------
  386. // return a pointer to a null Pascal string.
  387. StringPtr sNullStr( void )
  388. {
  389.     return (StringPtr)"\p";
  390. }
  391.  
  392. //----------------------------------------------------------------------
  393. // copy the Pascal string pointed to by sSrc to the pascal string pointed to by sDst
  394. StringPtr sCopyStr(
  395.     StringPtr    sSrc,
  396.     StringPtr    sDst )
  397. {
  398. #ifndef _68000_
  399.     register short i = sSrc[0];
  400.     register StringPtr sDst2 = sDst;
  401.  
  402.     do
  403.         *sDst2++ = *sSrc++;
  404.     while (i--);
  405. #else
  406.     asm
  407.     {
  408.         move.l    sSrc,a0
  409.         move.l    sDst,a1
  410.         clr.w    d0
  411.         move.b    (a0),d0
  412. @loop        move.b    (a0)+,(a1)+
  413.         dbf        d0,@loop
  414.     }
  415. #endif
  416.     return(sDst);
  417. }
  418.  
  419. //----------------------------------------------------------------------
  420. // clear the iLength characters (starting with the length byte) of the (Pascal) string sSrc.
  421. StringPtr sClearStr(Str255 sSrc,short iLength)
  422. {
  423. #ifndef _68000_
  424.     while (iLength--)
  425.         *(sSrc++) = 0;
  426. #else
  427.     asm
  428.     {
  429.         moveq.l    #0,d0
  430.         move.l    d0,d1
  431.         move.l    sSrc,a0
  432.         move.w    iLength,d0
  433. @loop    move.b    d1,(a0)+
  434.         dbf        d0,@loop
  435.     }
  436. #endif
  437.     return(sSrc);
  438. }
  439.  
  440. //----------------------------------------------------------------------
  441. // append the Pascal string sSrc to the Pascal string sDst.
  442. StringPtr sAppendStr(StringPtr sSrc, StringPtr sDst)
  443. {
  444. #ifndef _68000_
  445.     register short i;
  446.     register StringPtr sDst2;
  447.  
  448.     sDst2 = sDst + *sDst + 1;
  449.     *sDst += i = *sSrc++;
  450.     while (i--)
  451.         *sDst2++ = *sSrc++;
  452. #else
  453.     asm
  454.     {
  455.         move.l    sSrc,a0
  456.         clr.w    d0
  457.         move.b    (a0)+,d0
  458.         beq        @done
  459.         move.l    sDst,a1
  460.         clr.w    d1
  461.         move.b    (a1),d1
  462.         add.b    d0,(a1)+
  463.         add.w    d1,a1
  464. @loop    move.b    (a0)+,(a1)+
  465.         dbf        d0,@loop
  466. @done:
  467.     }
  468. #endif
  469.     return(sDst);
  470. }
  471.  
  472. //----------------------------------------------------------------------
  473. // copy the string sSrc into the string sDst and make it fit in iMaxWidth pixels
  474. // using the current font, size, and style by trimming characters and replacing
  475. // with and elipsis '…'.
  476. StringPtr sTrimText(StringPtr sSrc,StringPtr sDst,register short iMaxWidth)
  477. {
  478. #if 1
  479. //    if (StringWidth(sCopyStr(sSrc,sDst)) > iMaxWidth)
  480.  
  481.     sCopyStr(sSrc,sDst);
  482.     if (TextWidth(sDst+1, 0, sDst[0]) > iMaxWidth)
  483.     {
  484.         sDst[sDst[0]] = '…';
  485. //        while (sDst[0] > 1 && StringWidth(sDst) > iMaxWidth)
  486.         while (sDst[0] > 1 && TextWidth(sDst+1, 0, sDst[0]) > iMaxWidth)
  487.         {
  488.             sDst[--sDst[0]] = '…';
  489.         }
  490.     }
  491.     return(sDst);
  492. #else
  493.     // This is the int'l utils version.
  494.     sCopyStr(sSrc, sDst);
  495.     TruncString(iMaxWidth, sDst, smTruncEnd);
  496. #endif
  497. }
  498.  
  499. //----------------------------------------------------------------------
  500. StringPtr sFilterStr(StringPtr sSrc,StringPtr sDst)
  501. {
  502. #ifndef _68000_
  503.  
  504. // $$$$$ must write this in C if it's needed
  505. //#error sFilterStr not written in C yet.
  506.     DebugStr("\p sFilterStr: not written in C yet.");
  507.  
  508. #else
  509.     asm
  510.     {
  511.         move.l    sSrc,a0
  512.         move.l    sDst,a1
  513.         clr.w    d1
  514.         move.b    (a0)+,d1
  515.         move.b    d1,(a1)+
  516.         subq.w    #1,d1
  517. @loop    move.b    0(a0,d1.w),d0
  518.         cmpi.b    #' ',d0
  519.         bcs        @bad
  520.         cmpi.b    #0xAD,d0
  521.         beq        @bad
  522.         cmpi.b    #0xB0,d0
  523.         bcs        @good
  524.         cmpi.b    #0xB4,d0
  525.         beq        @good
  526.         cmpi.b    #0xBB,d0
  527.         bcs        @bad
  528.         cmpi.b    #0xBD,d0
  529.         beq        @bad
  530.         cmpi.b    #0xC2,d0
  531.         bcs        @good
  532.         cmpi.b    #0xC7,d0
  533.         bcs        @bad
  534.         cmpi.b    #0xD6,d0
  535.         beq        @bad
  536.         cmpi.b    #0xD9,d0
  537.         bcs        @good
  538. @bad    move.b    #'.',d0
  539. @good    move.b    d0,0(a1,d1.w)
  540.         dbf        d1,@loop
  541.         move.l    sDst,d0
  542.     }
  543. #endif
  544. }
  545.  
  546. //----------------------------------------------------------------------
  547. // convert the char into hex and append to the string sDst.
  548. StringPtr sAppendHexChar(char c0,StringPtr sDst)
  549. {
  550. #ifndef _68000_
  551.  
  552. // $$$$$ must write this in C if it's needed
  553. //#error sAppendHexChar not written in C yet.
  554.     DebugStr("\p sAppendHexChar: not written in C yet.");
  555.  
  556. #else
  557.     asm
  558.     {
  559.         move.l    sDst,a0
  560.         clr.w    d0
  561.         move.b    (a0),d0
  562.         move.b    c0,d1
  563.         lsr.b    #4,d1
  564.         ori.b    #'0',d1
  565.         cmpi.b    #'9'+1,d1
  566.         bcs        @1
  567.         addi.b    #7,d1
  568. @1        move.b    d1,1(a0,d0.w)
  569.         move.b    c0,d1
  570.         andi.b    #0xf,d1
  571.         ori.b    #'0',d1
  572.         cmpi.b    #'9'+1,d1
  573.         bcs        @2
  574.         addi.b    #7,d1
  575. @2        move.b    d1,2(a0,d0.w)
  576.         addq.b    #2,(a0)
  577.         move.l    sDst,d0
  578.     }
  579. #endif
  580. }
  581.  
  582. //----------------------------------------------------------------------
  583. // convert the short into hex and append to the string sDst.
  584. StringPtr sAppendHexShort(short i0,StringPtr sDst)
  585. {
  586.     return(sAppendHexChar((char) i0,sAppendHexChar((char) (i0 >> 8),sDst)));
  587. }
  588.  
  589. //----------------------------------------------------------------------
  590. // convert the long into hex and append to the string sDst.
  591. StringPtr sAppendHexLong(long l0,StringPtr sDst)
  592. {
  593.     return(sAppendHexShort((short) l0,sAppendHexShort((short) (l0 >> 16),sDst)));
  594. }
  595.  
  596. //----------------------------------------------------------------------
  597. // convert lLength bytes of the data at pBuffer to hex and append to the string sDst.
  598. StringPtr sAppendHexToStr(StringPtr sDst,Ptr pBuffer,long lLength)
  599. {
  600.     while (lLength--)
  601.         sAppendHexChar(*pBuffer++,sDst);
  602.     return(sDst);
  603. }
  604.  
  605. //----------------------------------------------------------------------
  606. // convert lLength bytes of the data at pBuffer into the hex string sDst.
  607. StringPtr sHexToStr(StringPtr sDst,Ptr pBuffer,long lLength)
  608. {
  609.     sDst[0] = 0;
  610.     return (sAppendHexToStr(sDst,pBuffer,lLength));
  611. }
  612.  
  613. //----------------------------------------------------------------------
  614. // if true, return the C String to append to make an English word plural.
  615. // if false, return the C String to append to make an English word singular.
  616. Ptr pPluralStrC(Boolean bPlural)
  617. {
  618.     GetIndString(pluralStr,CStringsID,41);        // 's'
  619.     ptocstr(pluralStr);
  620.     GetIndString(singularStr,CStringsID,42);    // ''
  621.     ptocstr(singularStr);
  622.     return (bPlural ? (Ptr) pluralStr : (Ptr) singularStr);
  623. }
  624.  
  625. //----------------------------------------------------------------------
  626. // if true, return the Pascal string to append to make an English word plural.
  627. // if false, return the Pascal string to append to make an English word singular.
  628. StringPtr sPluralStr(Boolean bPlural)
  629. {
  630.     GetIndString(pluralStr,CStringsID,41);        // 's'
  631.     GetIndString(singularStr,CStringsID,42);    // ''
  632.     return (bPlural ? pluralStr : singularStr);
  633. }
  634.  
  635. //----------------------------------------------------------------------
  636. // Compare the 2 strings and return true if they are the same, false if not.
  637. Boolean bStrCmp(StringPtr src,StringPtr dst)
  638. {
  639. short    i;
  640.  
  641.     if (src == dst)
  642.         return true;
  643.  
  644.     for (i=0; i <= src[0]; i++)
  645.         if (src[i] != dst[i])
  646.             return false;
  647.  
  648.     return true;
  649. }
  650.  
  651. //----------------------------------------------------------------------
  652. Boolean bCStrCmp(char *src,char *dst)
  653. {
  654.     if (src == dst)
  655.         return true;
  656.  
  657.     while (true)
  658.     {
  659.         if (*src != *dst)
  660.             return false;
  661.  
  662.         if (*src == '\0')
  663.             return true;
  664.  
  665.         src++;
  666.         dst++;
  667.     }
  668.  
  669.     return (*src == *dst);
  670. }
  671.  
  672. #if 0
  673. //----------------------------------------------------------------------
  674. sPrependStr(sSrc,sDst)
  675. {
  676.     BlockMoveData( sDst+1, sDst+1+sSrc[0], sDst[0] );
  677.     BlockMoveData( sSrc+1, sDst+1, sSrc[0] );
  678.     sDst[0] += sSrc[0];
  679. }
  680. #endif
  681.  
  682. //----------------------------------------------------------------------
  683. // iJust from GetSysJust(), 0 for left justified, -1 for right justified.
  684. void drawInfoLine(StringPtr sField, StringPtr sValue, short iJust)
  685. {
  686. GrafPtr        ourPort;
  687. Point         pStart;
  688. Style        stFace;
  689.  
  690.     GetPort(&ourPort);
  691.  
  692.     GetPen(&pStart);                // save the current pen location.
  693.     stFace = ourPort->txFace;        // save the current style
  694.  
  695.     TextFace(bold);
  696.     MoveTo(pStart.h - ((iJust ? -1 : 1) * TextWidth(sField+1, 0, sField[0])), pStart.v);
  697.     DrawString(sField);
  698.     TextFace(stFace);
  699.  
  700.     MoveTo(pStart.h + ((iJust ? -1 : 1) * 6), pStart.v);
  701.     DrawString(sValue);
  702.  
  703.     TextFace(stFace);                // restore the style
  704.     MoveTo(pStart.h, pStart.v);        // restore the pen location.
  705. }
  706.  
  707. //----------------------------------------------------------------------
  708. void drawRJInfoLine(StringPtr sField,StringPtr sValue)
  709. {
  710. GrafPtr        ourPort;
  711. Point         pStart;
  712. short        iFont, iSize;
  713. Style        stFace;
  714.  
  715.     GetPort(&ourPort);
  716.  
  717.     GetPen(&pStart);
  718.  
  719.     iFont = ourPort->txFont;
  720.     iSize = ourPort->txSize;
  721.     stFace = ourPort->txFace;
  722.  
  723.     TextFace(bold);
  724.     MoveTo(pStart.h-TextWidth(sField+1, 0, sField[0])-4, pStart.v);
  725. //    MoveTo(pStart.h-StringWidth(sField)-4, pStart.v);
  726.     DrawString(sField);
  727.     TextFace(stFace);
  728.  
  729.     MoveTo(pStart.h+68-TextWidth(sValue+1, 0, sValue[0]), pStart.v);
  730. //    MoveTo(pStart.h+68-StringWidth(sValue), pStart.v);
  731.     DrawString(sValue);
  732.  
  733.     TextFont(iFont);
  734.     TextSize(iSize);
  735.     TextFace(stFace);
  736.  
  737.     MoveTo(pStart.h,pStart.v);
  738. }
  739.  
  740.